package com.sc.nft.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.date.DateUtil;
import com.sc.nft.dao.*;
import com.sc.nft.entity.*;
import com.sc.nft.entity.dto.*;
import com.sc.nft.entity.vo.SaasTaskAwardDetailsListVO;
import com.sc.nft.enums.RedisKeyEnum;
import com.sc.nft.enums.SaasTaskConfigurationEnum;
import com.sc.nft.enums.SaasTaskParticipatorEnum;
import com.sc.nft.enums.SaasTaskTypeEnum;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.service.SaasTaskAwardDetailsService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.redisson.Redisson;
import org.redisson.api.RLock;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.TimeUnit;

/**
 * 任务奖励详情表(SaasTaskAwardDetails)表服务实现类
 *
 * @author 王伟成
 * @since 2024-01-11 15:08:24
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class SaasTaskAwardDetailsServiceImpl implements SaasTaskAwardDetailsService {

    private final SaasTaskAwardDetailsDao saasTaskAwardDetailsDao;

    private final SaasTaskMeetConditionsOptionDao saasTaskMeetConditionsOptionDao;

    private final SaasTaskAwardDao saasTaskAwardDao;

    private final SaasTaskDao saasTaskDao;

    private final SaasUserTaskDao saasUserTaskDao;

    private final DigitalCollectionDao digitalCollectionDao;

    private final EquityPropsDao equityPropsDao;

    private final SaasTaskMeetConditionsDao saasTaskMeetConditionsDao;

    private final SaasTaskStageConditionsDao saasTaskStageConditionsDao;

    private final Redisson redisson;



    @Override
    public SaasTaskAwardDetailsListVO list(SaasTaskAwardDetailsListDTO saasTaskAwardDetailsListDTO) {
        SaasTaskAwardDetailsListVO saasTaskAwardDetailsListVO = new SaasTaskAwardDetailsListVO();
        List<SaasTaskAwardDTO> resultList = new ArrayList<>();
        // 任务奖励主表
        List<SaasTaskAward> saasTaskAwardsList = saasTaskAwardDao.getByTaskIdAndStageId(saasTaskAwardDetailsListDTO.getTaskId(),saasTaskAwardDetailsListDTO.getStageId());
        saasTaskAwardsList.forEach(saasTaskAward -> {
            SaasTaskAwardDTO saasTaskAwardDTO = new SaasTaskAwardDTO();
            saasTaskAwardDTO.setCollectionId(saasTaskAward.getCollectionId());
            if (saasTaskAward.getCollectionId() != null) {
                DigitalCollection digitalCollection = digitalCollectionDao.getById(saasTaskAward.getCollectionId());
                if (BeanUtil.isNotEmpty(digitalCollection)) {
                    saasTaskAwardDTO.setFirstTitle(digitalCollection.getFirstTitle());
                } else {
                    throw new GlobalRunTimeException("任务持仓藏品异常");
                }
            }
            saasTaskAwardDTO.setWeight(saasTaskAward.getWeight());
            // 任务奖励详情表,把ID获取出来集合,放到集合里面一起查询出来.写入SaasTaskAwardDetailsDTO结构里面,需要获取的只是名字.这个查询的是权益道具的名字
            List<SaasTaskAwardDetails> saasTaskAwardDetailsList = saasTaskAwardDetailsDao.getByTaskAwardIdAndTaskId(saasTaskAward.getId(), saasTaskAwardDetailsListDTO.getTaskId());
            List<SaasTaskAwardDetailsDTO> saasTaskAwardDetailsDTOS = BeanUtil.copyToList(saasTaskAwardDetailsList, SaasTaskAwardDetailsDTO.class);
            // 通过权益道具id获取名字.把名字挨个赋值给SaasTaskAwardDetailsDTO
            saasTaskAwardDetailsDTOS.forEach(saasTaskAwardDetailsDTO -> {
                EquityProps equityProps = equityPropsDao.getById(saasTaskAwardDetailsDTO.getEquityPropsId());
                if (BeanUtil.isNotEmpty(equityProps)) {
                    saasTaskAwardDetailsDTO.setFirstTitle(equityProps.getFirstTitle());
                } else {
                    throw new GlobalRunTimeException("权益道具异常");
                }
            });
            saasTaskAwardDTO.setAward(saasTaskAwardDetailsDTOS);
            resultList.add(saasTaskAwardDTO);
        });

        saasTaskAwardDetailsListVO.setList(resultList);
        return saasTaskAwardDetailsListVO;
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void audit(SaasTaskAuditDTO saasTaskAuditDTO) {
        RLock lock = redisson.getLock(RedisKeyEnum.SAAS_TASK_LOCK_ADMIN.getKey());
        try {
            if (lock.tryLock(30, TimeUnit.SECONDS)) {
                // 验证器.不合法会抛异常
                saasTaskAuditDTO.validator();
                Long taskId = saasTaskAuditDTO.getId();
                SaasTask saasTask = saasTaskDao.getById(taskId);
                if (saasTask.getTaskConfiguration() != SaasTaskConfigurationEnum.UNDER_REVIEW) {
                    throw new GlobalRunTimeException("任务未提交审核,请检查");
                }
                // 通过任务的数量,获取最大的阶段上限,比对是否一致 不一致的话不让改.
                Integer taskIdMaxUpperLimit = saasTaskStageConditionsDao.getTaskIdMaxUpperLimit(taskId);
                if (!taskIdMaxUpperLimit.equals(saasTask.getTaskTotalSum())) {
                    throw new GlobalRunTimeException("任务总数与阶段上限最大值不一致,请检查");
                }
                // 修改任务状态
                saasTaskDao.audit(saasTaskAuditDTO);
            } else {
                throw new GlobalRunTimeException("服务器拥挤");
            }
        } catch (InterruptedException e) {
            throw new RuntimeException(e);
        }finally {
            if (lock.isLocked()) {
                lock.unlock();
            }
        }
    }
    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modification(SaasTaskModificationDTO saasTaskModificationDTO) {
        SaasTask saasTask = saasTaskDao.getById(saasTaskModificationDTO.getId());
        // 验证
        saasTaskModificationDTO.validator(saasTask, saasTaskMeetConditionsOptionDao.getByTaskIdAndType(saasTaskModificationDTO.getId(), 1));

        // 把所有的东西都要修改一下,把时间更正.把saasTaskMeetConditionsOption表里面的对应任务id和type=1的删除.让后重新组合一批新的写入.
        if (saasTask.getTaskParticipator()== SaasTaskParticipatorEnum.HOLD_COLLECTION) {
            // 新的持仓
            newPosition(saasTaskModificationDTO, saasTask);
        }
        saasTask.setTaskEnd(saasTaskModificationDTO.getEndTime());
        // 任务在修改之后,对应的任务的已经触发的用户.也要把结束时间给修改掉,一起给延期 否则的话会出现问题.
        SaasTaskMeetConditions saasTaskMeetConditions = saasTaskMeetConditionsDao.getByTaskId(saasTask.getId());
        SaasTaskTypeEnum taskType = saasTaskMeetConditions.getTaskType();
        Date taskEnd = saasTask.getTaskEnd();
        if (taskType==SaasTaskTypeEnum.ACCUMULATED_CONSUMPTION_AMOUNT) {
            taskEnd= DateUtil.offsetDay(taskEnd,15);
        }
        saasUserTaskDao.modificationTask(saasTask.getId(),taskEnd);
        saasTaskDao.updateById(saasTask);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void modificationAward(SaasTaskAwardPackStageDTO saasTaskAwardPackStageDTO) {
        // 干掉奖励的组,在重新写入奖励
        saasTaskStageConditionsDao.removeByTaskId(saasTaskAwardPackStageDTO.getTaskId());
        // 干掉奖励详情
        saasTaskAwardDao.removeByTaskId(saasTaskAwardPackStageDTO.getTaskId());
        // 干掉奖励详细配置
        saasTaskAwardDetailsDao.removeByTaskId(saasTaskAwardPackStageDTO.getTaskId());
        for (QuestRewardStagesAndRewardsDTO data : saasTaskAwardPackStageDTO.getRewards()) {
                // 新增一条新的.
                SaasTaskStageConditions saasTaskStageConditions = new SaasTaskStageConditions();
                saasTaskStageConditions.setSaasTaskId(saasTaskAwardPackStageDTO.getTaskId());
                saasTaskStageConditions.setUpperLimit(data.getUpperLimit());
                saasTaskStageConditions.setLowerLimit(data.getLowerLimit());
                saasTaskStageConditions.setRemainQuota(data.getUpperLimit()-data.getLowerLimit());
                saasTaskStageConditionsDao.save(saasTaskStageConditions);
                data.addValidator(saasTaskDao.getById(saasTaskAwardPackStageDTO.getTaskId()));
                batchSave(data.getAward(),saasTaskAwardPackStageDTO.getTaskId(),saasTaskStageConditions.getId());
        }
        // 修改过后要把这个任务的状态修改掉
        SaasTaskAuditDTO saasTaskAuditDTO=new SaasTaskAuditDTO();
        saasTaskAuditDTO.setId(saasTaskAwardPackStageDTO.getTaskId());
        saasTaskAuditDTO.setTaskConfiguration(SaasTaskConfigurationEnum.NOT_SUBMITTED_FOR_REVIEW);
        saasTaskDao.audit(saasTaskAuditDTO);
    }

    private void newPosition(SaasTaskModificationDTO saasTaskModificationDTO, SaasTask saasTask) {
        // 干掉原来的持仓要求,这里需要分辨出来对应的类型,不要把任务的关联删掉.
        saasTaskMeetConditionsOptionDao.deleteBySaasTaskIdAndType(saasTask.getId(),1);
        SaasTaskMeetConditions saasTaskMeetConditions = saasTaskMeetConditionsDao.getByTaskId(saasTask.getId());
        // 创建新的持仓要求
        List<SaasTaskMeetConditionsOption>saasTaskMeetConditionsOptions=new ArrayList<>();
        for (Long collectionId : saasTaskModificationDTO.getCollectionIds()) {
            SaasTaskMeetConditionsOption saasTaskMeetConditionsOption = new SaasTaskMeetConditionsOption();
            saasTaskMeetConditionsOption.setConditionId(collectionId);
            saasTaskMeetConditionsOption.setSaasTaskId(saasTask.getId());
            saasTaskMeetConditionsOption.setType(1);
            saasTaskMeetConditionsOption.setTaskType(saasTaskMeetConditions.getTaskType());
            saasTaskMeetConditionsOptions.add(saasTaskMeetConditionsOption);
        }
        saasTaskMeetConditionsOptionDao.saveBatch(saasTaskMeetConditionsOptions);
    }
    private void batchSave(List<SaasTaskAwardDTO> award,Long taskId,Long stageId) {
        award.forEach(saasTaskAwardDTO -> {
            SaasTaskAward saasTaskAward = BeanUtil.copyProperties(saasTaskAwardDTO, SaasTaskAward.class);
            saasTaskAward.setSaasTaskId(taskId);
            saasTaskAward.setStageId(stageId);
            saasTaskAwardDao.save(saasTaskAward);
            saasTaskAwardDTO.getAward().forEach(saasTaskAwardDetailsDTO -> {
                saasTaskAwardDetailsDTO.setTaskAwardId(saasTaskAward.getId());
                saasTaskAwardDetailsDTO.setSaasTaskId(taskId);
            });
            saasTaskAwardDetailsDao.saveBatch(BeanUtil.copyToList(saasTaskAwardDTO.getAward(), SaasTaskAwardDetails.class));
        });
    }
}
